﻿using MultiDAQ_Analysis.View;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// 高速UDP数据接收器 - 动态CPU优化版本
/// 专为高性能数据采集设计，支持动态负载调整
/// </summary>
public class HighSpeedUdpReceiver : IDisposable
{
    #region 常量定义
    private const int DEFAULT_UDP_PORT = 5000;
    private const int SOCKET_BUFFER_SIZE = 128 * 1024 * 1024; // 64MB缓冲区
    private const int MAX_PACKET_SIZE = 65507; // UDP最大包大小
    private const int BATCH_DEQUEUE_SIZE = 1000;
    private const int RECEIVE_TIMEOUT_MS = 100; // 接收超时
    private const int MAX_QUEUE_SIZE = 50000; // 最大队列大小
    #endregion

    #region 字段
    private readonly UltraHighPerformanceChannelParser _parser;
    private readonly int _port;
    private Socket _udpSocket;
    private Thread _receiveThread;
    private Thread _processingThread;
    private volatile bool _isReceiving;
    private volatile bool _isProcessing;
    private readonly IPEndPoint _localEndPoint;
    private readonly byte[] _receiveBuffer;
    private readonly ConcurrentQueue<byte[]> _packetQueue;

    // 性能统计
    private long _totalReceivedPackets;
    private long _totalReceivedBytes;
    private long _totalDroppedPackets;
    private long _totalProcessedPackets;
    private DateTime _lastStatsTime;
    private DateTime _startTime;

    // 动态调整相关
    private volatile int _idleReceiveCount;
    private volatile int _idleProcessCount;
    private long _lastReceivedCount;
    private long _lastProcessedCount;
    private readonly object _statsLock = new object();

    // 取消令牌
    private readonly CancellationTokenSource _cancellationTokenSource;
    #endregion

    #region 属性
    public bool IsRunning => _isReceiving && _isProcessing;
    public long TotalReceivedPackets => _totalReceivedPackets;
    public long TotalReceivedBytes => _totalReceivedBytes;
    public long TotalDroppedPackets => _totalDroppedPackets;
    public long TotalProcessedPackets => _totalProcessedPackets;
    public int PacketQueueSize => _packetQueue.Count;
    #endregion

    #region 构造函数
    public HighSpeedUdpReceiver(UltraHighPerformanceChannelParser parser, int port = DEFAULT_UDP_PORT)
    {
        _parser = parser ?? throw new ArgumentNullException(nameof(parser));
        _port = port;
        _localEndPoint = new IPEndPoint(IPAddress.Any, _port);
        _receiveBuffer = new byte[MAX_PACKET_SIZE];
        _packetQueue = new ConcurrentQueue<byte[]>();
        _cancellationTokenSource = new CancellationTokenSource();

        // 初始化处理线程
        _processingThread = new Thread(AdaptiveProcessPackets)
        {
            IsBackground = true,
            Name = "UDP-Processor",
            Priority = ThreadPriority.Normal // 降低优先级
        };

        _lastStatsTime = DateTime.UtcNow;
        _startTime = DateTime.UtcNow;

        Console.WriteLine($"[UDP接收器] 已创建，端口: {_port}");
    }
    #endregion

    #region 公共方法
    public void Start()
    {
        if (_isReceiving) return;

        try
        {
            // 创建并配置UDP Socket
            _udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            _udpSocket.ReceiveBufferSize = SOCKET_BUFFER_SIZE;
            _udpSocket.SendBufferSize = SOCKET_BUFFER_SIZE;
            _udpSocket.ReceiveTimeout = RECEIVE_TIMEOUT_MS;
            _udpSocket.Bind(_localEndPoint);

            _startTime = DateTime.UtcNow;
            _lastStatsTime = _startTime;

            // 启动接收线程
            _isReceiving = true;
            _receiveThread = new Thread(AdaptiveReceiveLoop)
            {
                IsBackground = true,
                Name = "UDP-Receiver",
                Priority = ThreadPriority.AboveNormal // 接收保持较高优先级
            };
            _receiveThread.Start();

            // 启动处理线程
            _isProcessing = true;
            _processingThread.Start();

            Console.WriteLine($"[UDP接收器] 已启动，端口: {_port}, 缓冲区: {SOCKET_BUFFER_SIZE / 1024 / 1024}MB");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"[UDP接收器错误] 启动失败: {ex.Message}");
            Stop();
            throw;
        }
    }

    public void Stop()
    {
        _isReceiving = false;
        _isProcessing = false;
        _cancellationTokenSource.Cancel();

        Console.WriteLine("[UDP接收器] 正在停止...");

        try
        {
            _udpSocket?.Close();
        }
        catch { /* 忽略关闭异常 */ }

        // 等待线程结束
        _receiveThread?.Join(2000);
        _processingThread?.Join(2000);

        PrintFinalStats();
        Console.WriteLine("[UDP接收器] 已停止");
    }
    #endregion

    #region 自适应接收循环
    private void AdaptiveReceiveLoop()
    {
        EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
        Console.WriteLine("[UDP接收器] 接收线程已启动");

        while (_isReceiving && !_cancellationTokenSource.Token.IsCancellationRequested)
        {
            try
            {
                int bytesReceived = _udpSocket.ReceiveFrom(_receiveBuffer, ref remoteEndPoint);

                if (bytesReceived > 0)
                {
                    _idleReceiveCount = 0; // 重置空闲计数

                    Interlocked.Increment(ref _totalReceivedPackets);
                    Interlocked.Add(ref _totalReceivedBytes, bytesReceived);

                    // 复制数据到新缓冲区
                    byte[] packetData = new byte[bytesReceived];
                    Buffer.BlockCopy(_receiveBuffer, 0, packetData, 0, bytesReceived);
                    _packetQueue.Enqueue(packetData);

                    // 智能队列管理
                    ManageQueue();
                }

                // 性能统计（降低频率到5秒）
                if ((DateTime.UtcNow - _lastStatsTime).TotalSeconds >= 5.0)
                {
                    ReportPerformance();
                    _lastStatsTime = DateTime.UtcNow;
                }
            }
            catch (SocketException sex) when (sex.SocketErrorCode == SocketError.TimedOut)
            {
                // 超时是正常的，进行自适应等待
                _idleReceiveCount++;
                AdaptiveWaitReceive();
            }
            catch (SocketException sex) when (sex.SocketErrorCode == SocketError.Interrupted)
            {
                break; // 正常中断
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[UDP接收器错误] 接收异常: {ex.Message}");
                Thread.Sleep(10);
            }
        }

        Console.WriteLine("[UDP接收器] 接收线程已停止");
    }

    private void AdaptiveWaitReceive()
    {
        // 根据空闲程度调整等待策略
        if (_idleReceiveCount < 5)
        {
            // 短期空闲，不等待
            return;
        }
        else if (_idleReceiveCount < 20) // 2秒内
        {
            Thread.Yield(); // 让出CPU时间片
        }
        else if (_idleReceiveCount < 50) // 5秒内
        {
            Thread.Sleep(1); // 短暂休眠
        }
        else if (_idleReceiveCount < 100) // 10秒内
        {
            Thread.Sleep(5); // 中等休眠
        }
        else
        {
            Thread.Sleep(10); // 长期无数据，较长休眠
        }
    }

    private void ManageQueue()
    {
        int currentSize = _packetQueue.Count;

        if (currentSize > MAX_QUEUE_SIZE)
        {
            // 动态丢弃策略：根据队列大小决定丢弃数量
            int dropCount = Math.Min(currentSize / 4, BATCH_DEQUEUE_SIZE * 2);

            for (int i = 0; i < dropCount && _packetQueue.TryDequeue(out _); i++)
            {
                Interlocked.Increment(ref _totalDroppedPackets);
            }

            if (dropCount > 0)
            {
                Console.WriteLine($"[UDP队列管理] 丢弃 {dropCount} 个包，当前队列: {_packetQueue.Count}");
            }
        }
    }
    #endregion

    #region 自适应包处理循环
    private void AdaptiveProcessPackets()
    {
        Console.WriteLine("[UDP处理器] 处理线程已启动");

        // 精确诊断主循环条件
        //Console.WriteLine("=== 主循环条件诊断 ===");
        //Console.WriteLine($"_isProcessing = {_isProcessing}");
        //Console.WriteLine($"_cancellationTokenSource == null: {_cancellationTokenSource == null}");

        //if (_cancellationTokenSource != null)
        //{
            //Console.WriteLine($"_cancellationTokenSource.Token.IsCancellationRequested = {_cancellationTokenSource.Token.IsCancellationRequested}");
        //}

        bool condition1 = _isProcessing;
        bool condition2 = !_cancellationTokenSource?.Token.IsCancellationRequested ?? false;
        bool whileCondition = condition1 && condition2;

        //Console.WriteLine($"条件1 (_isProcessing): {condition1}");
        //Console.WriteLine($"条件2 (!取消令牌): {condition2}");
        //Console.WriteLine($"while条件总结果: {whileCondition}");
        //Console.WriteLine("========================");

        if (!whileCondition)
        {
            //Console.WriteLine("[关键错误] while循环条件为false，无法进入主循环！");
            //Console.WriteLine("[关键错误] 处理线程将立即退出");
            return;
        }

        Console.WriteLine("[诊断] while循环条件正常，准备进入主循环");

        byte[][] batch = new byte[BATCH_DEQUEUE_SIZE][];
        int consecutiveEmptyCount = 0;
        long localProcessedCount = 0;
        int loopCounter = 0;

        try
        {
            while (_isProcessing && !_cancellationTokenSource.Token.IsCancellationRequested)
            {
                loopCounter++;


                //Console.WriteLine($"[主循环] 第 {loopCounter} 次循环开始");

                // 批量出队处理
                int count = 0;
                //Console.WriteLine($"[主循环] 准备从队列取数据，当前队列大小: {_packetQueue.Count}");

                while (count < BATCH_DEQUEUE_SIZE && _packetQueue.TryDequeue(out byte[] packet))
                {
                    batch[count++] = packet;
                    //Console.WriteLine($"[主循环] 成功取出包 #{count}, 长度: {packet.Length}");
                }

                if (count > 0)
                {
                    //Console.WriteLine($"[主循环] 本批次取出 {count} 个包，开始处理");
                    consecutiveEmptyCount = 0;
                    _idleProcessCount = 0;

                    // 批量提交到解析器
                    for (int i = 0; i < count; i++)
                    {
                        _parser.EnqueueData(batch[i], batch[i].Length);
                        //Console.WriteLine($"[主循环] 调用EnqueueData，包 #{i}");                        
                        //Console.WriteLine($"[主循环] EnqueueData调用完成，包 #{i}");
                        batch[i] = null;
                        localProcessedCount++;
                    }

                    // 定期更新全局计数器
                    if (localProcessedCount % 1000 == 0)
                    {
                        Interlocked.Add(ref _totalProcessedPackets, localProcessedCount);
                        localProcessedCount = 0;
                    }
                }
                else
                {
                    consecutiveEmptyCount++;
                    _idleProcessCount++;
                    //Console.WriteLine($"[主循环] 队列为空，空闲计数: {consecutiveEmptyCount}");

                    // 只循环几次就输出诊断信息
                    //if (loopCounter <= 5)
                    //{
                    //    Console.WriteLine($"[主循环] 第 {loopCounter} 次循环，队列为空，进入等待");
                    //}

                    // 自适应等待策略
                    AdaptiveWaitProcess(consecutiveEmptyCount);
                }

                // 前10次循环都输出状态
                //if (loopCounter <= 10)
                //{
                //    Console.WriteLine($"[主循环] 第 {loopCounter} 次循环结束，_isProcessing: {_isProcessing}, 取消令牌: {_cancellationTokenSource.Token.IsCancellationRequested}");
                //}

                // 如果循环太多次但没有数据，减少输出频率
                //if (loopCounter > 10 && loopCounter % 1000 == 0)
                //{
                //    Console.WriteLine($"[主循环] 已运行 {loopCounter} 次循环，队列大小: {_packetQueue.Count}");
                //}
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"[主循环异常] {ex.Message}");
            Console.WriteLine($"[主循环异常] 堆栈: {ex.StackTrace}");
        }

        // 最终更新计数器
        if (localProcessedCount > 0)
        {
            Interlocked.Add(ref _totalProcessedPackets, localProcessedCount);
        }

        Console.WriteLine($"[UDP处理器] 处理线程已停止，总循环次数: {loopCounter}");
        Console.WriteLine($"[UDP处理器] 停止时状态 - _isProcessing: {_isProcessing}, 取消令牌: {_cancellationTokenSource.Token.IsCancellationRequested}");
    }

    private void AdaptiveWaitProcess(int emptyCount)
    {
        if (emptyCount < 3)
        {
            Thread.Yield(); // 短期空闲，让出时间片
        }
        else if (emptyCount < 10)
        {
            Thread.Sleep(1); // 中期空闲，短暂休眠
        }
        else if (emptyCount < 50)
        {
            Thread.Sleep(2); // 较长空闲
        }
        else if (emptyCount < 200)
        {
            Thread.Sleep(5); // 长期空闲
        }
        else
        {
            Thread.Sleep(10); // 极长期空闲
        }
    }
    #endregion

    #region 性能报告
    private void ReportPerformance()
    {
        lock (_statsLock)
        {
            var now = DateTime.UtcNow;
            var totalElapsed = now - _startTime;
            var intervalElapsed = now - _lastStatsTime;

            if (totalElapsed.TotalSeconds <= 0) return;

            long currentReceived = _totalReceivedPackets;
            long currentProcessed = _totalProcessedPackets;

            // 计算速率
            double intervalPacketsPerSecond = 0;
            double intervalBytesPerSecond = 0;

            if (intervalElapsed.TotalSeconds > 0)
            {
                intervalPacketsPerSecond = (currentReceived - _lastReceivedCount) / intervalElapsed.TotalSeconds;
                intervalBytesPerSecond = _totalReceivedBytes / intervalElapsed.TotalSeconds;
            }

            double totalPacketsPerSecond = currentReceived / totalElapsed.TotalSeconds;
            double totalBytesPerSecond = _totalReceivedBytes / totalElapsed.TotalSeconds;
            double mbps = (totalBytesPerSecond * 8) / (1024 * 1024);

            // 只在有活动时报告详细信息
            if (intervalPacketsPerSecond > 0 || _packetQueue.Count > 0)
            {
                Console.WriteLine($"[UDP性能] 接收: {intervalPacketsPerSecond:F0} pps | 处理: {currentProcessed:N0} | 速率: {mbps:F2} Mbps | 队列: {_packetQueue.Count} | 丢弃: {_totalDroppedPackets}");
            }
            else if (totalElapsed.TotalSeconds > 10 && totalElapsed.TotalSeconds % 30 < 5) // 每30秒报告一次空闲状态
            {
                Console.WriteLine($"[UDP状态] 空闲中 | 总接收: {currentReceived:N0} | 总处理: {currentProcessed:N0} | 队列: {_packetQueue.Count}");
            }

            _lastReceivedCount = currentReceived;
            _lastProcessedCount = currentProcessed;
        }
    }

    private void PrintFinalStats()
    {
        var totalTime = DateTime.UtcNow - _startTime;

        Console.WriteLine("=== UDP接收器最终统计 ===");
        Console.WriteLine($"[运行时间] {totalTime.TotalSeconds:F1} 秒");
        Console.WriteLine($"[总接收包数] {_totalReceivedPackets:N0}");
        Console.WriteLine($"[总接收字节] {_totalReceivedBytes / 1024.0 / 1024.0:F2} MB");
        Console.WriteLine($"[总处理包数] {_totalProcessedPackets:N0}");
        Console.WriteLine($"[总丢弃包数] {_totalDroppedPackets:N0}");

        if (totalTime.TotalSeconds > 0)
        {
            double avgPacketsPerSec = _totalReceivedPackets / totalTime.TotalSeconds;
            double avgMbps = (_totalReceivedBytes * 8 / 1024.0 / 1024.0) / totalTime.TotalSeconds;

            Console.WriteLine($"[平均接收速率] {avgPacketsPerSec:F0} pps, {avgMbps:F2} Mbps");
            Console.WriteLine($"[处理效率] {(_totalProcessedPackets * 100.0 / Math.Max(1, _totalReceivedPackets)):F1}%");
            Console.WriteLine($"[丢包率] {(_totalDroppedPackets * 100.0 / Math.Max(1, _totalReceivedPackets)):F2}%");
        }

        Console.WriteLine("========================");
    }
    #endregion

    #region IDisposable实现
    public void Dispose()
    {
        Stop();
        _udpSocket?.Dispose();
        _cancellationTokenSource?.Dispose();

        // 清空队列
        while (_packetQueue.TryDequeue(out _)) { }
    }
    #endregion
}


